/* 
继承的目的：让子类的实例，除了具备子类提供的属性方法，还要具备父类提供的属性和方法 
实现继承的方案：
  1. 原型继承「让子类的原型对象指向父类的一个实例」
     Child.prototype = new Parent()
     问题：父类提供的属性和方法，全部都成为子类实例“公有”的属性方法；子类的原型对象被重定向后，丢失了 constructor 属性！！
     特点：原型继承并不是“拷贝式”继承（并不是把父亲的东西copy一份给儿子，而是让儿子基于原型链，找到父亲的方法，再去使用；这样就存在一个隐患，如果儿子基于原型链，把父亲原型上的方法改了，这样对父亲的其他实例也有影响！）

  2. call继承「把父类当做普通函数执行，让函数中的this指向子类的实例」
     function Child() {
        Parent.call(this,...) //this:子类的实例
        ...
     }
     问题：仅仅实现了“把父类私有的属性 继承给了 子类实例的私有属性「有冲突，则以子类为主」”，但是父类公有的方法并没有被子类实例继承过去！！
     特点：它是拷贝式继承

  3. 寄生组合式继承「把call继承和原型继承(变异版)混合在一起」
    function Child() {
        Parent.call(this) 「CALL继承部分：拷贝式继承」
        ...
    }
   「原型继承部分：非拷贝式继承」
    Child.prototype = Object.create(Parent.prototype)
    Child.prototype.constructor = Child
    基于这样的方案，就实现了：父亲私有给了儿子私有，父亲公有给了儿子公有！！

  4. 基于ES6中的class创建类，其自带了继承方案「原理类似于寄生组合式继承」
    class Child extends Parent{
        // 如果没有设置 constructor ，其内部也会默认实现一个“类似 call 继承”：把父类私有的变为子类私有的，只不过不会给父类传递任何实参
        // 如果需要在此处给父类传递实参，则必须写 constructor 函数；但是一旦设置了constructor函数，则在此函数第一行必须执行  super(...) 函数（否则会报错）
        constructor() {
            super(10, 20) //类似于 Parent.call(this,10,20)
            ...
        }
        ...
    }
*/

class Parent {
    // 给实例设置的私有属性
    constructor(x, y) {
        this.x = x
        this.y = y
    }
    // 处理原型对象
    sum() { }
}

class Child extends Parent {
    // 给实例设置的私有属性
    /* x = 100
    z = 300 */
    constructor() {
        super(10, 20)
        this.x = 100
        this.z = 300
    }
    // 处理原型对象
    minus() { }
}
let c = new Child()
console.log(c)


//=============================
/*
// 父类
function Parent() {
    this.x = 10
    this.y = 20
}
Parent.prototype.sum = function sum() {
    return this.x + this.y
}
// 子类
function Child() {
    Parent.call(this) //this:子类的实例c 「CALL继承部分」
    this.x = 100
    this.z = 300
}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child
Child.prototype.minus = function minus() {
    return this.z - this.x
}
let c = new Child()
console.log(c)
*/

//=============================
/* 
// 父类
function Parent() {
    this.x = 10
    this.y = 20
}
Parent.prototype.sum = function sum() {
    return this.x + this.y
}
// 子类
function Child() {
    this.x = 100
    this.z = 300
}
Child.prototype = new Parent()
Child.prototype.constructor = Child
Child.prototype.minus = function minus() {
    return this.z - this.x
}
let c = new Child() 
*/